-- Intercection with the entities in set 1 and the entities in set 2

function Intention:intersectionOfSet1EntitiesWithSet2Entities(set1Entities, goal)

	gLogger:enterGroup("Solve intersection of Set1 entity with one of Set2 entities")
	
	
	-- set 2 is entities (their property are used as values)
	-- get the set 2 in constraintTrackingTable
	
	local set2Entities = self:getSubConstraintTrackingTable(
		goal.constraint.set2EntitiesType, 
		goal.constraint.set2EntitiesNames,
		goal
	)

	
	-- reduce set 1 & 2  (we don't just calculate the common intersection because both sets can already be reduced by previous constraints)
	
	for entity1, entity1Values in pairs(set1Entities)
	do
		for entity2, entity2Values in pairs(set2Entities)
		do
		
			-- reduce set 1 with set 2
			
			gLogger:enterGroup("Reduce set 1 entity " .. entity1.type .. " " .. entity1.name .. " with set 2 entity "  .. entity2.type .. " " .. entity2.name)
			
			for entity1Value, entity1Probability in pairs(entity1Values)
			do
				if not entity2Values[entity1Value]
				then
					gLogger:log("Remove value " .. entity1Value.type .. " " .. entity1Value.name .. " from entity (from set1) " .. entity1.type .. " " .. entity1.name .. " " .. goal.constraint.property)
					
					entity1Values[entity1Value] = nil
				end
			end
			
			gLogger:leaveGroup()
			
			
			-- reduce set 2 with set 1
			
			gLogger:enterGroup("Reduce set 2 entity " .. entity2.type .. " " .. entity2.name .. " with set 1 entity "  .. entity1.type .. " " .. entity1.name)
			
			for entity2Value, entity2Probability in pairs(entity2Values)
			do
				if not entity1Values[entity2Value]
				then
					gLogger:log("Remove value " .. entity2Value.type .. " " .. entity2Value.name .. " from entity (from set2) " .. entity2.type .. " " .. entity2.name .. " " .. goal.constraint.property)
					
					entity2Values[entity2Value] = nil
				end
			end
			
			gLogger:leaveGroup()
		end
	end
	
	gLogger:leaveGroup()
end


-- Intercection with the unique entity in set 1 and at least one entity in set 2

function Intention:intersectionOfSet1EntityWithOneOfSet2Entities(set1Entities, goal)

	gLogger:enterGroup("Solve intersection of Set1 entity with one of Set2 entities")
	
	
	-- set 2 is entities (their property are used as values)
	-- get the set 2 in constraintTrackingTable
	
	local set2Entities = self:getSubConstraintTrackingTable(
		goal.constraint.set2EntitiesType, 
		goal.constraint.set2EntitiesNames,
		goal
	)

	
	-- Reduce set 2 entities with the unique entity in set 1
	
	local concatenedValuesOfSet2 = {}
	local entity1, entity1Values = next(set1Entities)
	
	assert(not next(set1Entities, entity1), "Set1 can only have one entity in this constraint solver")
	
	for entity2, entity2Values in pairs(set2Entities)
	do
		gLogger:enterGroup("Reduce set 2 entity " .. entity2.type .. " " .. entity2.name .. " with set 1 entity "  .. entity1.type .. " " .. entity1.name)
		
		for entity2Value, entity2Probability in pairs(entity2Values)
		do
			concatenedValuesOfSet2[entity2Value] = true
			
			if not entity1Values[entity2Value]
			then
				gLogger:log("Remove value " .. entity2Value.type .. " " .. entity2Value.name .. " from entity (from set2) " .. entity2.type .. " " .. entity2.name .. " " .. goal.constraint.property)
				
				entity2Values[entity2Value] = nil
			end
		end
		
		gLogger:leaveGroup()
	end		
		
		
	-- Reduce set 1 entity with set 2 concatened values
	--
	-- This is an approximation to avoid a part of the "many world" interpretation of QM.
	-- To be exact, we would have to explore each branch of the set2 entity in
	-- the next constraint solvers. Making it a tree exploration of constraints solving.
	
	gLogger:enterGroup("Reduce set 1 entity " .. entity1.type .. " " .. entity1.name .. " with concatened values of set 2")
	
	for entity1Value, entity1Probability in pairs(entity1Values)
	do
		if not concatenedValuesOfSet2[entity1Value]
		then
			gLogger:log("Remove value " .. entity1Value.type .. " " .. entity1Value.name .. " from entity (from set1) " .. entity1.type .. " " .. entity1.name .. " " .. goal.constraint.property)
			
			entity1Values[entity1Value] = nil
		end
	end
	
	gLogger:leaveGroup()
	gLogger:leaveGroup()
end


--- Intersection with the entities in Set2 and the values in Set2

function Intention:intersectionOfSet1EntityWithSet2Values(set1Entities, goal)

	gLogger:enterGroup("Solve intersection of Set1 entity with Set2 values")
	
	
	-- set 2 is entity references (as values for set 1 entities' property)
	
	local vn, set2EntitiesType = goal:getVariableNameAndValue(goal.constraint.set2ValuesEntitiesType)
	local vn, set2EntitiesNames = goal:getVariableNameAndValue(goal.constraint.set2ValuesEntitiesNames)
	
	local entity2Values = {}
	for i, set2EntitiesName in pairs(set2EntitiesNames)
	do
		entity2Values[gField.entityTypes[set2EntitiesType][set2EntitiesName]] = true
	end
	
	-- reduce set 1 with set 2 
	
	for entity1, entity1Values in pairs(set1Entities)
	do
		for entity1Value, entity1Probability in pairs(entity1Values)
		do
			if not entity2Values[entity1Value]
			then
				gLogger:log("Remove value " .. entity1Value.type .. " " .. entity1Value.name .. " from entity 1 " .. entity1.type .. " " .. entity1.name .. " " .. goal.constraint.property)
			
				entity1Values[entity1Value] = nil
			end
		end
	end
	
	gLogger:leaveGroup()
end